import { Raycaster, Vector2 } from 'three';
import * as THREE from 'three';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js';
import {
  BlendFunction,
  SelectiveBloomEffect,
  EffectComposer as _EffectComposer,
  EffectPass as _EffectPass,
  RenderPass as _RenderPass,
} from 'postprocessing';

import { BLOOM_SCENE, ENTIRE_SCENE } from '.';

const bloomLayer = new THREE.Layers();
bloomLayer.set(BLOOM_SCENE);
const bloomIgnore = ['AxesHelper']; // 跟辉光光晕有关的变量
const materials = {};
const darkMaterial = new THREE.MeshBasicMaterial({ color: 'black' });

export function initBloomPassesComposer(option, renderPassScene) {
  const { renderer, scene, camera, containerId } = option;
  const el = document.getElementById(containerId);

  const params = {
    exposure: 1,
    bloomStrength: 1.5,
    bloomThreshold: 0,
    bloomRadius: 0,
  };

  // 去掉锯齿—1
  const effectFXAA = new ShaderPass(FXAAShader);
  effectFXAA.uniforms['resolution'].value.set(0.6 / window.innerWidth, 0.6 / window.innerHeight);
  effectFXAA.renderToScreen = true;

  // 渲染通道
  let renderScene;
  if (renderPassScene) {
    renderScene = renderPassScene;
  } else {
    renderScene = new RenderPass(scene, camera);
  }

  // 添加光晕效果—2
  const bloomPass = new UnrealBloomPass(new THREE.Vector2(el.offsetWidth, el.offsetHeight), 1.5, 0, 0.85);
  bloomPass.threshold = params.bloomThreshold;
  bloomPass.strength = params.bloomStrength;
  bloomPass.radius = params.bloomRadius;

  // 着色器通道容器–放进容器里
  const bloomComposer = new EffectComposer(renderer);
  bloomComposer.addPass(renderScene);
  bloomComposer.addPass(bloomPass);
  bloomComposer.addPass(effectFXAA);

  return {
    bloomComposer,
    passes: [renderScene, effectFXAA],
  };
}

export const enableGlow = (model, materialName = 'dengpao') => {
  model.traverse((obj) => {
    if (obj.isMesh) {
      if (Array.isArray(obj.material)) {
        obj.material.forEach((material, index) => {
          if (material.name === materialName) {
            const newMaterial = new THREE.MeshLambertMaterial({ color: 0xffd700 });
            console.log('[enableGlow]命中');
            obj.position.z = 30;
            obj.layers.enable(BLOOM_SCENE);
            obj.material[index] = newMaterial;
          }
        });
      } else {
        if (obj.material.name === materialName) {
          const newMaterial = new THREE.MeshLambertMaterial({ color: 0xffd700 });
          obj.position.z = 30;
          obj.layers.enable(BLOOM_SCENE);
          obj.material = newMaterial;
        }
      }
    }
  });
};

export function initMxintBloomPassesComposer(option) {
  const { scene, renderer, camera } = option;
  const renderPassScene = new RenderPass(scene, camera);
  const { bloomComposer } = initBloomPassesComposer(option, renderPassScene);
  const finalPass = new ShaderPass(
    new THREE.ShaderMaterial({
      uniforms: {
        baseTexture: { value: null },
        bloomTexture: { value: bloomComposer.renderTarget2.texture },
      },
      vertexShader: `
        varying vec2 vUv;
        void main() {
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
        }
        `,
      fragmentShader: `
        uniform sampler2D baseTexture;
        uniform sampler2D bloomTexture;
        varying vec2 vUv;
        void main() {
            gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );
        }
        `,
      defines: {},
    }),
    'baseTexture'
  );
  finalPass.needsSwap = true;
  const finalComposer = new EffectComposer(renderer);
  finalComposer.addPass(renderPassScene);
  finalComposer.addPass(finalPass);

  const renderBloom = () => {
    scene.traverse((obj) => {
      if (obj instanceof THREE.Scene) {
        // 此处忽略Scene，否则场景背景会被影响
        materials.scene = obj.background;
        obj.background = null;
        // return;
      }
      console.log(obj);

      if (
        obj instanceof THREE.Sprite || // 此处忽略Sprite
        bloomIgnore.includes(obj.type) ||
        (obj.isMesh && bloomLayer.test(obj.layers) === false) // 判断与辉光是否同层
      ) {
        materials[obj.uuid] = obj.material;
        // 将不需要辉光的材质设置为黑色
        obj.material = darkMaterial;
      }
    });
    bloomComposer.render();
    scene.traverse((obj) => {
      if (materials[obj.uuid]) {
        obj.material = materials[obj.uuid]; // 恢复原材质
        delete materials[obj.uuid];
      }
    });
    finalComposer.render();
  };
  return {
    renderBloom,
    finalComposer,
  };
}

export function initMxintBloomPassesComposer_thirdparty(option) {
  const { scene, renderer, camera } = option;
  const finalComposer = new _EffectComposer(renderer);
  const bloomEffect = new SelectiveBloomEffect(scene, camera, {
    blendFunction: BlendFunction.ADD,

    mipmapBlur: true,

    luminanceThreshold: 0.4,

    luminanceSmoothing: 0.2,

    intensity: 3.0,
  });
  finalComposer.addPass(new _RenderPass(scene, camera));
  finalComposer.addPass(new _EffectPass(camera, bloomEffect));
  return { finalComposer, bloomEffect };
}
